{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/usr/local/lib/python3.5/dist-packages/h5py/__init__.py:36: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.\n",
      "  from ._conv import register_converters as _register_converters\n",
      "/usr/local/lib/python3.5/dist-packages/sklearn/cross_validation.py:41: DeprecationWarning: This module was deprecated in version 0.18 in favor of the model_selection module into which all the refactored classes and functions are moved. Also note that the interface of the new CV iterators are different from that of this module. This module will be removed in 0.20.\n",
      "  \"This module will be removed in 0.20.\", DeprecationWarning)\n"
     ]
    }
   ],
   "source": [
    "from utils import *\n",
    "import tensorflow as tf\n",
    "from sklearn.cross_validation import train_test_split\n",
    "import time\n",
    "import random\n",
    "import os\n",
    "os.environ['CUDA_VISIBLE_DEVICES'] = ''"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['negative', 'positive']\n",
      "10662\n",
      "10662\n"
     ]
    }
   ],
   "source": [
    "trainset = sklearn.datasets.load_files(container_path = 'data', encoding = 'UTF-8')\n",
    "trainset.data, trainset.target = separate_dataset(trainset,1.0)\n",
    "print (trainset.target_names)\n",
    "print (len(trainset.data))\n",
    "print (len(trainset.target))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "train_X, test_X, train_Y, test_Y = train_test_split(trainset.data, trainset.target,\n",
    "                                                    test_size = 0.2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "vocab from size: 20332\n",
      "Most common words [('film', 1453), ('movie', 1270), ('one', 727), ('like', 721), ('story', 477), ('much', 386)]\n",
      "Sample data [556, 2600, 3622, 11345, 36, 8710, 219, 150, 19, 3998] ['rock', 'destined', '21st', 'centurys', 'new', 'conan', 'hes', 'going', 'make', 'splash']\n"
     ]
    }
   ],
   "source": [
    "concat = ' '.join(trainset.data).split()\n",
    "vocabulary_size = len(list(set(concat)))\n",
    "data, count, dictionary, rev_dictionary = build_dataset(concat, vocabulary_size)\n",
    "print('vocab from size: %d'%(vocabulary_size))\n",
    "print('Most common words', count[4:10])\n",
    "print('Sample data', data[:10], [rev_dictionary[i] for i in data[:10]])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "GO = dictionary['GO']\n",
    "PAD = dictionary['PAD']\n",
    "EOS = dictionary['EOS']\n",
    "UNK = dictionary['UNK']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "def get_one_triplet(input_data, input_labels, n_labels):\n",
    "    index = np.random.choice(n_labels, 2, replace=False)\n",
    "    label_positive = index[0]\n",
    "    label_negative = index[1]\n",
    "\n",
    "    indexes = np.where(input_labels == index[0])[0]\n",
    "    np.random.shuffle(indexes)\n",
    "\n",
    "    data_anchor = input_data[indexes[0], :]\n",
    "    data_positive = input_data[indexes[1], :]\n",
    "\n",
    "    indexes = np.where(input_labels == index[1])[0]\n",
    "    np.random.shuffle(indexes)\n",
    "    data_negative = input_data[indexes[0], :]\n",
    "\n",
    "    return data_anchor, data_positive, data_negative, label_positive, label_positive, label_negative\n",
    "\n",
    "def compute_euclidean_distance(x, y):\n",
    "    d = tf.square(tf.subtract(x, y))\n",
    "    return tf.sqrt(tf.reduce_sum(d))\n",
    "\n",
    "def compute_triplet_loss(anchor_feature, positive_feature, negative_feature, margin=0.01):\n",
    "    d_p_squared = tf.square(compute_euclidean_distance(anchor_feature, positive_feature))\n",
    "    d_n_squared = tf.square(compute_euclidean_distance(anchor_feature, negative_feature))\n",
    "    loss = tf.maximum(0., d_p_squared - d_n_squared + margin)\n",
    "    return tf.reduce_mean(loss), tf.reduce_mean(d_p_squared), tf.reduce_mean(d_n_squared)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Model:\n",
    "    def __init__(self, size_layer, num_layers, embedded_size,\n",
    "                 dict_size, dimension_output,margin=0.2):\n",
    "        \n",
    "        def cells(reuse=False):\n",
    "            return tf.nn.rnn_cell.BasicRNNCell(size_layer,reuse=reuse)\n",
    "        \n",
    "        def rnn(embedded,reuse=False):\n",
    "            with tf.variable_scope('model', reuse=reuse):\n",
    "                rnn_cells = tf.nn.rnn_cell.MultiRNNCell([cells() for _ in range(num_layers)])\n",
    "                outputs, _ = tf.nn.dynamic_rnn(rnn_cells, embedded, dtype = tf.float32)\n",
    "                W = tf.get_variable('w',shape=(size_layer, dimension_output),initializer=tf.orthogonal_initializer())\n",
    "                b = tf.get_variable('b',shape=(dimension_output),initializer=tf.zeros_initializer())\n",
    "                return tf.matmul(outputs[:, -1], W) + b\n",
    "            \n",
    "        with tf.device('/cpu:0'):    \n",
    "            self.ANCHOR = tf.placeholder(tf.int32, [None, None])\n",
    "            self.POSITIVE = tf.placeholder(tf.int32, [None, None])\n",
    "            self.NEGATIVE = tf.placeholder(tf.int32, [None, None])\n",
    "            self.Y_ANCHOR = tf.placeholder(tf.int32, [None])\n",
    "            self.Y_POSITIVE = tf.placeholder(tf.int32, [None])\n",
    "            self.Y_NEGATIVE = tf.placeholder(tf.int32, [None])\n",
    "            encoder_embeddings = tf.Variable(tf.random_uniform([dict_size, embedded_size], -1, 1))\n",
    "            anchor_embedded = tf.nn.embedding_lookup(encoder_embeddings, self.ANCHOR)\n",
    "            positive_embedded = tf.nn.embedding_lookup(encoder_embeddings, self.POSITIVE)\n",
    "            negative_embedded = tf.nn.embedding_lookup(encoder_embeddings, self.NEGATIVE)\n",
    "            self.output_anchor = rnn(anchor_embedded,False)\n",
    "            self.output_positive = rnn(positive_embedded,True)\n",
    "            self.output_negative = rnn(negative_embedded,True)\n",
    "            self.cost, positives, negatives = compute_triplet_loss(self.output_anchor, \n",
    "                                                          self.output_positive, \n",
    "                                                          self.output_negative)\n",
    "            self.optimizer = tf.train.GradientDescentOptimizer(1e-4).minimize(self.cost)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "size_layer = 128\n",
    "num_layers = 2\n",
    "embedded_size = 128\n",
    "dimension_output = len(trainset.target_names)\n",
    "maxlen = 50\n",
    "batch_size = 128"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "tf.reset_default_graph()\n",
    "sess = tf.InteractiveSession()\n",
    "model = Model(size_layer,num_layers,embedded_size,len(dictionary),dimension_output)\n",
    "sess.run(tf.global_variables_initializer())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "train_X = str_idx(train_X,dictionary,maxlen)\n",
    "test_X = str_idx(test_X,dictionary,maxlen)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "epoch: 1, loss: 0.000000\n",
      "epoch: 2, loss: 4.933203\n",
      "epoch: 3, loss: 10.419333\n",
      "epoch: 4, loss: 0.000000\n",
      "epoch: 5, loss: 0.000000\n",
      "epoch: 6, loss: 7.707937\n",
      "epoch: 7, loss: 0.000000\n",
      "epoch: 8, loss: 3.788496\n",
      "epoch: 9, loss: 0.000000\n",
      "epoch: 10, loss: 0.000000\n"
     ]
    }
   ],
   "source": [
    "for i in range(10):\n",
    "    lasttime = time.time()\n",
    "    batch_anchor = np.zeros((batch_size,maxlen))\n",
    "    batch_positive = np.zeros((batch_size,maxlen))\n",
    "    batch_negative = np.zeros((batch_size,maxlen))\n",
    "    batch_y_anchor = np.zeros((batch_size))\n",
    "    batch_y_positive = np.zeros((batch_size))\n",
    "    batch_y_negative = np.zeros((batch_size))\n",
    "    for k in range(batch_size):\n",
    "        batch_anchor[k], batch_positive[k], batch_negative[k], batch_y_anchor[k], batch_y_positive[k], batch_y_negative[k] = get_one_triplet(train_X, train_Y, dimension_output)\n",
    "    loss, _ = sess.run([model.cost,model.optimizer],\n",
    "                       feed_dict={model.ANCHOR:batch_anchor,\n",
    "                                  model.POSITIVE:batch_positive,\n",
    "                                  model.NEGATIVE:batch_negative,\n",
    "                                  model.Y_ANCHOR:batch_y_anchor,\n",
    "                                  model.Y_POSITIVE:batch_y_positive,\n",
    "                                  model.Y_NEGATIVE:batch_y_negative})\n",
    "    print('epoch: %d, loss: %f'%(i+1,loss))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(2133, 2)"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "logits_train = sess.run(model.output_positive,feed_dict={model.POSITIVE:train_X})\n",
    "logits_test = sess.run(model.output_positive,feed_dict={model.POSITIVE:test_X})\n",
    "logits_test.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "             precision    recall  f1-score   support\n",
      "\n",
      "   negative       0.50      0.52      0.51      1054\n",
      "   positive       0.51      0.48      0.50      1079\n",
      "\n",
      "avg / total       0.50      0.50      0.50      2133\n",
      "\n"
     ]
    }
   ],
   "source": [
    "from scipy.spatial.distance import cdist\n",
    "label_test = []\n",
    "for i in range(logits_test.shape[0]):\n",
    "    label_test.append(train_Y[np.argsort(cdist(logits_train, [logits_test[i,:]], 'cosine').ravel())[0]])\n",
    "print(metrics.classification_report(test_Y, label_test, target_names = trainset.target_names))\n",
    "\n",
    "#print(metrics.classification_report(test_Y, np.argmax(logits_test,axis=1), target_names = trainset.target_names))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "import seaborn as sns\n",
    "sns.set()\n",
    "from matplotlib import offsetbox"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7fb7c68c5780>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "ax_min = np.min(logits_test,0)\n",
    "ax_max = np.max(logits_test,0)\n",
    "ax_dist_sq = np.sum((ax_max-ax_min)**2)\n",
    "plt.figure(figsize=(8,8))\n",
    "ax = plt.subplot(111)\n",
    "shown_images = np.array([[1., 1.]])\n",
    "colors = ['b','r']\n",
    "for i in range(logits_test.shape[0]):\n",
    "    dist = np.sum((logits_test[i] - shown_images)**2, 1)\n",
    "    if np.min(dist) < 3e-4*ax_dist_sq:\n",
    "        continue\n",
    "    shown_images = np.r_[shown_images, [logits_test[i]]]\n",
    "    plt.scatter(logits_test[i,0],logits_test[i,1],c=colors[test_Y[i]])\n",
    "plt.legend(['negative','positive'])\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
